package com.alipay.rebate.shop.scheduler;

import com.alipay.rebate.shop.constants.UserIncomeConstant;
import com.alipay.rebate.shop.dao.mapper.CommissionFreezeLevelSettingsMapper;
import com.alipay.rebate.shop.dao.mapper.IncomeCommissionFreezeLevelMapper;
import com.alipay.rebate.shop.dao.mapper.UserIncomeMapper;
import com.alipay.rebate.shop.dao.mapper.UserMapper;
import com.alipay.rebate.shop.helper.JpushHelper;
import com.alipay.rebate.shop.model.CommissionFreezeLevelSettings;
import com.alipay.rebate.shop.model.UserIncome;
import com.alipay.rebate.shop.pojo.userincome.IncomeSchedulerRsp;
import com.alipay.rebate.shop.utils.DateUtil;
import com.alipay.rebate.shop.utils.DecimalUtil;
import com.alipay.rebate.shop.utils.ListUtil;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import javax.annotation.Resource;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component
public class UserIncomeScanner {

  private Logger logger = LoggerFactory.getLogger(UserIncomeScanner.class);
  @Resource
  CommissionFreezeLevelSettingsMapper freezeLevelSettingsMapper;
  @Resource
  UserIncomeMapper userIncomeMapper;
  @Autowired
  private SqlSessionFactory sqlSessionFactory;
  @Autowired
  private JpushHelper jpushHelper;

  @Transactional
  public void scanFreezeUserIncome() {

    List<IncomeSchedulerRsp> taobaoFreezeIncomes = userIncomeMapper.selectFreezeIncome();
    List<IncomeSchedulerRsp> pddFreezeIncomes = userIncomeMapper.selectPddOrdersFreezeIncome();
    List<IncomeSchedulerRsp> jdFreezeIncomes = userIncomeMapper.selectJdOrdersFreezeIncome();

    logger.debug("taobaoFreezeIncomes is : {}",taobaoFreezeIncomes);
    logger.debug("pddFreezeIncomes is : {}",pddFreezeIncomes);
    logger.debug("jdFreezeIncomes is : {}",jdFreezeIncomes);

    // 处理淘宝收益记录
    proccessFreezeUserIncome(taobaoFreezeIncomes,UserIncomeConstant.FREEZING_TYPE);
    // 处理拼多多收益记录
    proccessFreezeUserIncome(pddFreezeIncomes,UserIncomeConstant.FREEZING_PDD_TYPE);
    // 处理京东收益记录
    proccessFreezeUserIncome(jdFreezeIncomes,UserIncomeConstant.FREEZING_JD_TYPE);

  }

  public void proccessFreezeUserIncome(List<IncomeSchedulerRsp> freezeIncomes,int type) {

    logger.debug("freezeIncomes : {}",freezeIncomes);
    if(ListUtil.isEmptyList(freezeIncomes)){
      return ;
    }

    // 获取佣金冻结等级比例配置
    List<CommissionFreezeLevelSettings> levelSettings =
        freezeLevelSettingsMapper.getCommissionFreezeLevelSettingsMapperByType(type);
    logger.debug("levelSettings is : {}",levelSettings);

    // batch方式获取mapper对象
    List<String> alias = new ArrayList<>();
    // 通过batch方式，修改收益记录状态和添加用户集分宝
    SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    UserIncomeMapper userIncomeMapper = sqlSession.getMapper(UserIncomeMapper.class);
    IncomeCommissionFreezeLevelMapper incomeCommissionFreezeLevelMapper =
        sqlSession.getMapper(IncomeCommissionFreezeLevelMapper.class);
    logger.debug("userMapper is : {}",userMapper);
    logger.debug("userIncomeMapper is : {}",userIncomeMapper);

    Set<String> tradeIdList = new HashSet<>();
    //取出user_income表中的trade_id
    for(IncomeSchedulerRsp userIncome: freezeIncomes){
      tradeIdList.add(userIncome.getTradeId());
    }
    logger.debug("tradeIdList is : {}",tradeIdList);


    for (String tradeId : tradeIdList){

      // 获取tradeId 相同的记录
      List<IncomeSchedulerRsp> sameTradeIdIspList = getSameTradeIdIsp(tradeId,freezeIncomes);
      logger.debug("sameTradeIdIspList is : {}",sameTradeIdIspList);
      // 记录是否大于1条
      if(!isRecordMoreThanOne(sameTradeIdIspList)){
        logger.debug("just one record");
        for (IncomeSchedulerRsp userIncome : sameTradeIdIspList){ // 记录小于1条，判断记录是否可以转账
          if (checkIfCanPaid(userIncome,levelSettings)){
            alias.add(String.valueOf(userIncome.getUserId()));
            updateInfo(userIncome,userMapper,incomeCommissionFreezeLevelMapper);
          }
          // 已经处理过的从列表中移除
          freezeIncomes.remove(userIncome);
        }
      }
      else{ // 记录大于1条
        // 获取金额最大的那条记录
        IncomeSchedulerRsp maxIncome = getMaxMoneyRecord(sameTradeIdIspList);
        logger.debug("maxIncome is : {}",maxIncome);
        //判断是否可以转账
        boolean flag = checkIfCanPaid(maxIncome, levelSettings);
        if (flag){
          //可以转账
          for (IncomeSchedulerRsp userIncome : sameTradeIdIspList){
            alias.add(String.valueOf(userIncome.getUserId()));
            updateInfo(userIncome,userMapper,incomeCommissionFreezeLevelMapper);
          }
        }
      }
    }

    logger.debug("finally flush");
    sqlSession.flushStatements();

    if(!ListUtil.isEmptyList(alias)){
      // 推送返利消息给用户
      jpushHelper.orderCommissionPush(alias);
    }

  }

  private List<IncomeSchedulerRsp> getSameTradeIdIsp(String tradeId, List<IncomeSchedulerRsp> freezeIncomes){

    List<IncomeSchedulerRsp> rspList = new ArrayList<>();
    for (IncomeSchedulerRsp userIncome : freezeIncomes){
      if (userIncome.getTradeId() != null) {
        if (userIncome.getTradeId().equals(tradeId)) {
          rspList.add(userIncome);
        }
      }
    }
    return rspList;
  }

  private boolean isRecordMoreThanOne(List<IncomeSchedulerRsp> incomeSchedulerRsps){
    return incomeSchedulerRsps.size() >  1;
  }

  private IncomeSchedulerRsp getMaxMoneyRecord(List<IncomeSchedulerRsp> rspList){
    BigDecimal money = new BigDecimal(0.00);
    IncomeSchedulerRsp maxIncome = null;

    //找出最大金额的记录
    for (IncomeSchedulerRsp income : rspList){
      if (income.getMoney().compareTo(money) >= 0){
        maxIncome = income;
        money = maxIncome.getMoney();
      }
    }

    return maxIncome;
  }

  private IncomeSchedulerRsp getMinMoneyRecord(List<IncomeSchedulerRsp> rspList){
    BigDecimal money = new BigDecimal(0.00);
    IncomeSchedulerRsp minIncome = null;

    //找出最大金额的记录
    for (IncomeSchedulerRsp income : rspList){
      if (income.getMoney().compareTo(money) >= 0){
        minIncome = income;
        money = minIncome.getMoney();
      }
    }
    for (IncomeSchedulerRsp income : rspList){
      if (income.getMoney().compareTo(money) == -1){
        minIncome = income;
        money = minIncome.getMoney();
      }
    }
    return minIncome;
  }

  // 查看时间信息，判断是否可以转账
  private boolean checkIfCanPaid(IncomeSchedulerRsp userIncome,
      List<CommissionFreezeLevelSettings> levelSettings){

    int freezeDay  = 0;
    // 找到冻结天数
    for(CommissionFreezeLevelSettings settings: levelSettings){
      if(settings.getBegin().compareTo(userIncome.getMoney()) <=0 &&
      settings.getEnd().compareTo(userIncome.getMoney()) >0){
        logger.debug("suitable CommissionFreezeLevelSettings is : {}",settings);
        freezeDay = settings.getFreezeDay();
        break;
      }
    }

    // 判断时间是否已经达到冻结天数设置时间
    LocalDateTime paidTimePlus = DateUtil.getLocationDateTime(userIncome.getPaidTime()).plusDays(freezeDay);
    LocalDateTime now = LocalDateTime.now();
    logger.debug("now : {}", now);
    logger.debug("paidTimePlus : {}", paidTimePlus);
    if(paidTimePlus.isBefore(now)){
      logger.debug("time reached, should paid for user");
      return true;
    }

    return false;
  }

  private void updateInfo(IncomeSchedulerRsp userIncome, UserMapper userMapper,
      IncomeCommissionFreezeLevelMapper incomeCommissionFreezeLevelMapper){
    logger.debug("updateInfo userIncome");
    UserIncome nUserIncome = new UserIncome();
    nUserIncome.setUserIncomeId(userIncome.getUserIncomeId());
    nUserIncome.setStatus(UserIncomeConstant.IS_PAID);

    userIncomeMapper.updateByPrimaryKeySelective(nUserIncome);
    userMapper.plusUserUit(DecimalUtil.convertMoneyToUit(userIncome.getMoney()),userIncome.getUserId());
    incomeCommissionFreezeLevelMapper.deleteByIncomeId(userIncome.getUserIncomeId());
  }

  public void processRoadTypeIsNullUserIncome(List<IncomeSchedulerRsp> userIncomes){
    logger.debug("userIncomes is : {}",userIncomes);
    // 获取所有的tradeId
    Set<String> tradeIdList = new HashSet<>();
    for (IncomeSchedulerRsp userIncome : userIncomes){
      logger.debug("userIncome tradeId is : {}",userIncome.getTradeId());
      tradeIdList.add(userIncome.getTradeId());
    }
    logger.debug("tradeId is : {}",tradeIdList);

    for (String tradeId : tradeIdList){
      logger.debug("tradeId is : {}",tradeId);
      if (tradeId == null){
        continue;
      }
      // 获取tradeId 相同的记录
      List<IncomeSchedulerRsp> sameTradeIdIspList = getSameTradeIdIsp(tradeId,userIncomes);

      handleDifferentListSize(sameTradeIdIspList,tradeId);
    }
  }

  private void handleDifferentListSize(List<IncomeSchedulerRsp> sameTradeIdIspList,String tradeId){

    int roadType = 0;
    // 记录是否大于1条
    if(!isRecordMoreThanOne(sameTradeIdIspList)){
      logger.debug("just one record");
      for (IncomeSchedulerRsp sameTradeIdIsp : sameTradeIdIspList) {
        roadType = 0;
        userIncomeMapper.updateUserIncomeByTradeId(roadType, tradeId,sameTradeIdIsp.getMoney());
      }
    }
    if (sameTradeIdIspList.size() == 2 ){
      logger.debug("just two record");
      IncomeSchedulerRsp maxMoneyRecord = getMaxMoneyRecord(sameTradeIdIspList);
      userIncomeMapper.updateUserIncomeByTradeId(roadType,maxMoneyRecord.getTradeId(),maxMoneyRecord.getMoney());
      for (IncomeSchedulerRsp sameTradeId :sameTradeIdIspList){
        if (!sameTradeId.getMoney().equals(maxMoneyRecord.getMoney())){
          roadType = 1;
          userIncomeMapper.updateUserIncomeByTradeId(roadType,sameTradeId.getTradeId(),sameTradeId.getMoney());
        }
      }
    }
    if (sameTradeIdIspList.size() == 3){
      logger.debug("just record");
      // 获取最大的金额
      IncomeSchedulerRsp maxMoneyRecord = getMaxMoneyRecord(sameTradeIdIspList);
      userIncomeMapper.updateUserIncomeByTradeId(roadType,maxMoneyRecord.getTradeId(),maxMoneyRecord.getMoney());
      // 获取最小的金额

      IncomeSchedulerRsp minMoneyRecord = getMinMoneyRecord(sameTradeIdIspList);
      roadType = 2;
      userIncomeMapper.updateUserIncomeByTradeId(roadType,minMoneyRecord.getTradeId(),minMoneyRecord.getMoney());

      userIncomeMapper.updateUserIncomeByTradeId(roadType,minMoneyRecord.getTradeId(),minMoneyRecord.getMoney());
      for (IncomeSchedulerRsp sameTradeId :sameTradeIdIspList){
        if (!sameTradeId.getMoney().equals(maxMoneyRecord.getMoney()) && !sameTradeId.getMoney().equals(minMoneyRecord.getMoney())){
          roadType = 1;
          userIncomeMapper.updateUserIncomeByTradeId(roadType,sameTradeId.getTradeId(),sameTradeId.getMoney());
        }
      }
    }

  }

}
